package ia1011.zanzibar.processor.fsm;

import java.util.ArrayList;
import java.util.Iterator;

import ia1011.zanzibar.rules.Rule;

/**
 * The class represents a state of a FSM built over feature structures
 * 
 * @author Alessandro Perrino (creator)
 * @author <br> Bastianelli E. emanuele.bastianelli@gmail.com (modifier)
 * @author <br> Caponi E. emiliano.caponi@gmail.com (modifier)
 * @author <br> Castellucci G. castellucci.giuseppe@gmail.com (modifier)
 * @author <br> Rossi A. berardino.viola@gmail.com (modifier)
 *   
 */

public class State {
	// is true is the state is final
	boolean isFinal; 
	// if the state is final, contains the rule to be applied when the state is reached
	Rule matchingRule; 
	// the set of transition starting from the state
	ArrayList<Transition> transitions;
	
	public String nome = null;
	
	/**
	 * create a new non-final state 
	 */
	public State() {
		matchingRule = null;
		isFinal = false;
		transitions = new ArrayList<Transition>();
	}
	
	/**
	 * add a new transion to the state
	 * @param transition transiton to add from the state  
	 */
	public void addTransition(Transition transition) {
		transitions.add(transition);
	}
	
	/**
	 * Get the index-th transition from the state
	 * @param index 
	 * @return the index-th transition from the state
	 */
	public Transition getTransition(int index) {
		return transitions.get(index);
	}
	
	/**
	 * 
	 * @return all transitions from the state
	 */
	public ArrayList<Transition> getTransitions() {
		return transitions;
	}
	
	/**
	 * 
	 * @return true if the state is final, false otherwise 
	 */
	public boolean isFinal() {
		return isFinal;
	}
	
	/**
	 * set the state as final state
	 */
	public void setFinal() {
		isFinal = true;
	}
	
	/**
	 * Sets the rule associated to the final state; in case the state is already associated to a rule, the one with
	 * highest weight is kept 
	 *
	 * @param rule the rule to set
	 */
	public void setRule(Rule rule) {
		if (matchingRule == null)
			matchingRule = rule;
		else
			if (matchingRule.getWeight() < rule.getWeight())
				matchingRule = rule;
	}
	
	
	
	/**
	 * 
	 * It should only be invoked on a state known to be final
	 * @return the rule linked to the final state
	 */
	public Rule getRule() {
		return matchingRule;
	}
	
	/**
	 * 
	 * Prints a simple representation of the transitions starting from the 
	 * state; it's recursively invoked on the target states. 
	 *
	 * @param index
	 * @return
	 */
	public int display(int index)
	{
		nome = String.valueOf(index);
		System.out.println();
		int j = index;
		if (isFinal()) {
			System.out.println("Stato finale "+index);
			System.out.println();
		}
		Iterator iter = transitions.iterator();
		while (iter.hasNext()) {
			Transition t = (Transition)iter.next();
			System.out.println("Stato "+nome+" -> ");
			if (t.getConstraint() != null)
				t.getConstraint().display();
			else
				System.out.println("null");
			if (t.getTarget().nome == null) {
				j = j+1;
				System.out.println(" -> Stato "+j);
				j = t.getTarget().display(j);
			} else {
				System.out.println(" -> Stato "+t.getTarget().nome);
				System.out.println();
			}
		}
		return j;
	}
}
